#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

//最多支持用户数量
#define MAXUSER  10
//每行的最大长度
#define MAXLEN   128

typedef struct accountinfo
{
	int id;
	char username[10];
	char password[10];
	float money;
} ACCOUNT;


ACCOUNT g_users[MAXUSER];  //全局数组，保存用户信息
ACCOUNT g_loginuser; //记录当前的登录用户
int g_pos;    //当前用户在数组中的位置
int g_count;  //用户的数量


//将格式字符串转换为账户的结构体
//格式：  账户id ; 用户名 ; 密码 ; 余额
ACCOUNT convertaccount(char* p)
{
	ACCOUNT t;
	char *tp;

	tp = strtok(p,";");
	sscanf(tp,"%d",&t.id);

	tp = strtok(NULL,";");
	sscanf(tp,"%s",&t.username);

	tp = strtok(NULL,";");
	sscanf(tp,"%s",&t.password);

	tp = strtok(NULL,";");
	sscanf(tp,"%f",&t.money);

	return t;
}

int init()
{
	char filename[]="account_in.txt";   //文本文件,每行信息包括 账户id ; 用户名 ; 密码 ; 余额 
	FILE *fp = NULL;
	char buff[128], *rp;
	int pos;

	printf("加载数据从文件 %s ....\n",filename);
	pos = 0; //代表用户数量
	fp = fopen(filename,"r");
	if (fp != NULL)
	{
		while (!feof(fp))
		{
			rp = fgets(buff,sizeof(buff),fp);  //从文件中读入1行信息
			if (rp != NULL)
			{
				//printf("%s",buff);
				if (pos < MAXUSER)
				{
					g_users[pos] = convertaccount(buff);
					pos++;
				}
			}
		}
		g_count = pos;
		fclose(fp);
	}

	return 0;
}

//显示用户信息
void displayuser(ACCOUNT user)
{
	printf("当前用户信息\n");
	printf("============\n");
	printf("用户帐号: %d\n",user.id);
	printf("用户姓名: %s\n",user.username);
	printf("用户密码: %s\n",user.password);
	printf("账户余额: %.2f\n",user.money);
}

//连续显示用户信息
void displayusers(int n)
{
	int i;
	printf("显示用户信息\n");
	printf("============\n");
	for (i=0;i<n;i++)
	{
		printf("%d;%s;%s;%.2f\n",g_users[i].id,g_users[i].username,
			g_users[i].password,g_users[i].money);
	}
}

//返回用户的位置，如果不存在，则返回 -1
int searchvaliduser(int userid,char* passwd)
{
	int i;
	int b1,pos;
	b1 = 0;
	pos = -1;
	i = 0;
	
	while (i<g_count)
	{
		//比较用户名和密码是否相同, strcmp函数相同返回0
		if (userid == g_users[i].id)
		{
			b1 = strcmp(passwd,g_users[i].password);
			if (b1 == 0)
			{
				pos = i; //记录位置，并退出循环
				break;
			}
		}
		i++;
	}
	return pos;
}

//用户验证功能
int userlogin(int userid,char* passwd)
{
	int valid,pos;

	valid = 0;
	pos = searchvaliduser(userid,passwd);
	if (pos >= 0)
	{
		valid = 1;
		g_loginuser = g_users[pos];  //设置为全局的登录用户，便于其他功能使用
		g_pos = pos;
	}
	return valid;
}


//登录界面
int loginview()
{
	int r,times;
	int uid;
	char password[10];
	printf("输入账户编号\n");
	scanf("%d",&uid);
	printf("输入用户密码\n");
	scanf("%s",&password);
	r = userlogin(uid,password);
	
	times = 1;
	while (( r == 0) && (times < 3))   //
	{
		times++;
		printf("密码错误，重新输入\n");
		scanf("%s",&password);
		r = userlogin(uid,password);
	}
	return r;
}

//把当前登录账户的信息放入数组中
void syncloginuser()
{
	g_users[g_pos] = g_loginuser;
}

//注意本界面是用户登录验证后显示
void welcome()
{
	system("CLS"); // 清屏
	printf("欢迎使用ATM机\n");
	printf("=============\n");
	printf("1. 取款           2. 查询\n");
	printf("3. 修改密码       4. 转账\n");
	printf("5. 退出系统 \n");
	printf("=============\n");
	printf("请注意账户安全\n");

}

int mainmenu();

//取款
void withdraw()
{
	char ch;
	int m;
	printf(">> 1.取款模块 <<\n");
	printf("输入取款金额\n");
	scanf("%d", &m);
	if ((m > 0) && ( m <= g_loginuser.money))
	{
		g_loginuser.money = g_loginuser.money - m; //此处需添加取款限制逻辑
		printf("请取出现金 %d\n",m);
		printf("余额为 %.2f\n",g_loginuser.money);
	}
	printf("任意键返回主菜单\n");
	ch = getch();
	mainmenu();
}

// 查询当前账户信息
void selectuser()
{
	char ch;
	printf(">> 2.查询模块 <<\n");
	displayuser(g_loginuser);
	printf("任意键返回主菜单\n");
	ch = getch();
	mainmenu();
}

//修改用户密码
void updatepassword()
{
	char ch;
	char oldpass[10],newpass[10],newpass2[10];

	printf(">> 3.修改密码 <<\n");
	printf("输入原密码\n");
	scanf("%s",oldpass);
	if ( strcmp(oldpass,g_loginuser.password) == 0)
	{
		printf("输入新密码\n");
		scanf("%s",newpass);
		printf("再输入一次新密码\n");
		scanf("%s",newpass2);
		if (strcmp(newpass,newpass2) == 0)  //注意strcmp比较时，相等返回0
		{
			strcpy(g_loginuser.password,newpass);
			printf("修改密码成功!\n");
		}
	}
	printf("任意键返回主菜单\n");
	ch = getch();
	mainmenu();
}

//查找用户账户是否存在,不存在返回 -1 ,存在返回位置
int isvalidaccount(int uid)
{
	int r = -1;
	int i;
	for (i=0;i<g_count;i++)
	{
		if ((uid == g_users[i].id) && (uid != g_loginuser.id))
		{
			r = i;
			break;
		}
	}
	return r;
}

//把当前账户的钱转到其他账户
void transfer()
{
	char ch;
	int uid;
	int pos;
	int m;
	printf(">> 4.转账模块 <<\n");
	printf("输入对方帐号\n");
	scanf("%d",&uid);
	
	pos = isvalidaccount(uid);
	if (pos != -1)
	{
		printf("输入转账金额\n");
		scanf("%d",&m);
		if (m <= g_loginuser.money)
		{
			g_loginuser.money = g_loginuser.money - m;
			g_users[pos].money = g_users[pos].money + m; 
			printf("转出 %d 到 %s \n",m,g_users[pos].username);
			printf("余额 %.2f \n",g_loginuser.money);
		}
	}
	printf("任意键返回主菜单\n");
	ch = getch();
	mainmenu();
}

//退出主菜单，注意将登录用户的信息写入数组中
void exitmenu()
{
	printf(">> 5.退出模块 <<\n");
	//此处需要同步修改全局数组中的用户信息
	syncloginuser();
}

int mainmenu()
{
	char ch;
	welcome();
	ch = getch();
	switch (ch)
	{
	case '1' : 
		withdraw(); //取款
		break;
	case '2' :
		selectuser();
		break;
	case '3':
		updatepassword();
		break;
	case '4':
		transfer();
		break;
	case '5':
	case 'q':
	case 'x':
		exitmenu();
		break;
	default:
		printf("输入无效，重新输入\n");
	}
	return 0;
}


//将用户信息转换为字符串形式，每行信息包括 账户id ; 用户名 ; 密码 ; 余额 
void getUserString(char* str,const ACCOUNT user)
{
	sprintf(str,"%d;%s;%s;%.2f\n",user.id,user.username,user.password,user.money);
	//printf("%s",str);
}

//保存用户信息到文本文件中
int saveinfo()
{
	char filename[]="account_out.txt";   //文本文件,每行信息包括 账户id ; 用户名 ; 密码 ; 余额 
	FILE *fp = NULL;
	char buff[128];
	int i;

	printf("保存数据到 %s ....\n",filename);

	fp = fopen(filename,"w");
	if (fp != NULL)
	{
		for (i=0;i<g_count;i++)
		{
			getUserString((char*)buff,g_users[i]);
			fputs(buff,fp);
		}		
		fclose(fp);
	}
	return 0;
}

int main()
{
	int r;
	init();
	//r = userlogin(2,"123456");
	r = loginview();
	if (r)
	{
		mainmenu();
		saveinfo();
	}
	else
	{
		printf("无效用户\n");
	}
	
	return 0;
}